#include "CasoDePrueba.h"
#include "Sistema.h"

#include "CastIterador.h"
#include "PaisPrueba.h"
#include "CiudadPrueba.h"
#include "RecursoPrueba.h"

#include <iostream>
using namespace std;

CasoDePrueba::CasoDePrueba()
{
	interfaz = new Sistema(10, 10, 20);
}

CasoDePrueba::~CasoDePrueba()
{
}

Cadena CasoDePrueba::GetNombre()const
{
	return "Casos de Prueba";
}

void CasoDePrueba::CorrerPruebaConcreta()
{
	Cadena altaPais = "Se da de alta el pais {0}";
	Cadena altaCiudad = "Se da de alta la ciudad {0}";
	char aux[2];
	aux[1] = '\0';
	char* chrNom = aux;
	for (nat i = 1; i < 5; i++)
	{
		chrNom[0] = '0' + i;
		Cadena cadNomPais(chrNom);
		Prueba::Verificar(interfaz->AltaPais(cadNomPais), OK, altaPais.DarFormato(cadNomPais));
		for (nat j = 1; j < 5; j++)
		{
			chrNom[0] = '0' + j;
			Cadena cadNomCiudad(chrNom);
			Prueba::Verificar(interfaz->AltaCiudad(cadNomPais, cadNomCiudad, i + j == 5), OK, altaCiudad.DarFormato(cadNomCiudad));
		}
	}

	Tupla<TipoRetorno, Puntero<Iterador<pPais>>> resultado = interfaz->ImprimirJuego();
	Prueba::Verificar(resultado.GetDato1(), OK, "Se devuelve el juego completo");
	if (resultado.GetDato1() == OK)
	{
		Array<Puntero<RecursoPrueba>> recursos;
		Array<Puntero<CiudadPrueba>> ciudades = Array<Puntero<CiudadPrueba>>(4);
		ciudades[0] = new CiudadPrueba("1");
		ciudades[1] = new CiudadPrueba("2");
		ciudades[2] = new CiudadPrueba("3");
		ciudades[3] = new CiudadPrueba("4");
		ciudades[0]->SetRecursos(recursos);
		ciudades[1]->SetRecursos(recursos);
		ciudades[2]->SetRecursos(recursos);
		ciudades[3]->SetRecursos(recursos);

		Array<Puntero<PaisPrueba>> paises = Array<Puntero<PaisPrueba>>(4);
		paises[0] = new PaisPrueba("1");
		paises[1] = new PaisPrueba("2");
		paises[2] = new PaisPrueba("3");
		paises[3] = new PaisPrueba("4");
		paises[0]->SetCiudades(ciudades, ciudades[3]);
		paises[1]->SetCiudades(ciudades, ciudades[2]);
		paises[2]->SetCiudades(ciudades, ciudades[1]);
		paises[3]->SetCiudades(ciudades, ciudades[0]);

		Verificar(resultado.GetDato2(), Puntero<Iterador<pPais>>(new CastIterador<PaisPrueba,IPais>(paises.ObtenerIterador())), "Se esperaba el pais {0}", "No se esperaba el pais {0}");
	}
}

template <class T>
void CasoDePrueba::Verificar(Puntero<Iterador<Puntero<T>>> obtenidos, Puntero<Iterador<Puntero<T>>> esperados, Cadena comentarioFalta, Cadena comentarioSobra)
{
	obtenidos->Reiniciar();
	esperados->Reiniciar();

	while (obtenidos->HayElemento())
	{
		Puntero<T> ptrObt = obtenidos->ElementoActual();
		obtenidos->Avanzar();
		if (esperados->HayElemento())
		{
			Puntero<T> ptrEsp = esperados->ElementoActual();
			esperados->Avanzar();
			Verificar(ptrObt, ptrEsp);
		}
		else
			Prueba::Verificar(ERROR, OK, comentarioSobra.DarFormato(ptrObt->ObtenerNombre()));
	}

	while (esperados->HayElemento())
	{
		Puntero<T> ptrEsp = esperados->ElementoActual();
		esperados->Avanzar();
		Prueba::Verificar(ERROR, OK, comentarioFalta.DarFormato(ptrEsp->ObtenerNombre()));
	}
}

void CasoDePrueba::Verificar(pPais obtenido, pPais esperado, Cadena comentario)
{
	Prueba::Verificar(obtenido == esperado ? OK : ERROR, OK, comentario.DarFormato(obtenido->ObtenerNombre(), esperado->ObtenerNombre()));
	Verificar(obtenido->ObtenerCapital(), esperado->ObtenerCapital(), "La capital obtenida es {0} y se esperaba {1}");
	Verificar(obtenido->Ciudades(), esperado->Ciudades(), "Se esperaba la ciudad {0}", "No se esperaba la ciudad {0}");
}

void CasoDePrueba::Verificar(pCiudad obtenido, pCiudad esperado, Cadena comentario)
{
	Prueba::Verificar(obtenido == esperado ? OK : ERROR, OK, comentario.DarFormato(obtenido->ObtenerNombre(), esperado->ObtenerNombre()));
}
